// internal/model/rolemodel.go
package model

import (
	"database/sql"
	"fmt"
	"probe-users/internal/errorx"

	"github.com/zeromicro/go-zero/core/stores/cache"
	"github.com/zeromicro/go-zero/core/stores/sqlx"
	"github.com/zeromicro/go-zero/core/syncx"
)

var _ RoleModel = (*customRoleModel)(nil)

type (
	// RoleModel 接口定义
	RoleModel interface {
		roleModel
		FindByName(name string) (*Role, error)
	}

	customRoleModel struct {
		*defaultRoleModel
	}
)

// NewRoleModel 创建角色模型实例
func NewRoleModel(conn sqlx.SqlConn, c cache.CacheConf) RoleModel {
	return &customRoleModel{
		defaultRoleModel: newDefaultRoleModel(conn, c),
	}
}

// FindByName 通过角色名查询角色
func (m *customRoleModel) FindByName(name string) (*Role, error) {
	role := new(Role)
	query := fmt.Sprintf("select %s from %s where name = ? limit 1", roleRows, m.table)
	err := m.QueryRowNoCache(role, query, name)
	switch err {
	case nil:
		return role, nil
	case sql.ErrNoRows:
		return nil, fmt.Errorf("%w: 角色名 %s 不存在", errorx.ErrRoleNotFound, name)
	default:
		return nil, err
	}
}

const (
	roleTable = "roles"
)

var roleRows = "`id`, `name`, `desc`, `created_at`, `updated_at`, `deleted_at`"

type roleModel interface {
	Insert(data *Role) (sql.Result, error)
	FindOne(id int64) (*Role, error)
	Update(data *Role) error
	Delete(id int64) error
}

type defaultRoleModel struct {
	conn  sqlx.SqlConn
	cache cache.Cache
	table string
}

func newDefaultRoleModel(conn sqlx.SqlConn, c cache.CacheConf) *defaultRoleModel {
	return &defaultRoleModel{
		conn:  conn,
		cache: cache.New(c, syncx.NewSingleFlight(), cache.NewStat("role"), errorx.ErrRoleNotFound),
		table: roleTable,
	}
}

func (m *defaultRoleModel) Insert(data *Role) (sql.Result, error) {
	query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?)", m.table, roleRows)
	return m.conn.Exec(query, data.ID, data.Name, data.Desc, data.CreatedAt, data.UpdatedAt)
}

func (m *defaultRoleModel) FindOne(id int64) (*Role, error) {
	role := new(Role)
	query := fmt.Sprintf("select %s from %s where id = ? limit 1", roleRows, m.table)
	err := m.QueryRowNoCache(role, query, id)
	switch err {
	case nil:
		return role, nil
	case sql.ErrNoRows:
		return nil, fmt.Errorf("%w: 角色ID %d 不存在", errorx.ErrRoleNotFound, id)
	default:
		return nil, err
	}
}

func (m *defaultRoleModel) Update(data *Role) error {
	query := fmt.Sprintf("update %s set %s where id = ?", m.table, "`name`=?, `desc`=?, `created_at`=?, `updated_at`=?, `deleted_at`=?")
	_, err := m.conn.Exec(query, data.Name, data.Desc, data.CreatedAt, data.UpdatedAt, data.DeletedAt, data.ID)
	return err
}

func (m *defaultRoleModel) Delete(id int64) error {
	query := fmt.Sprintf("delete from %s where id = ?", m.table)
	_, err := m.conn.Exec(query, id)
	return err
}

func (m *defaultRoleModel) QueryRowNoCache(dest interface{}, query string, args ...interface{}) error {
	return m.conn.QueryRow(dest, query, args...)
}